package main;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.util.Map;
import java.util.Vector;

import org.jacorb.orb.CDRInputStream;

import sql.DBConnection;
import utils.Constant;
import utils.ParserXML;
//import cdmw.logging.LogManager;

import com.coflight.cfl.IOData.Common.BasicATM.Misc.WarningOccurenceData;

import dds.DDSTypeManager;
import dds.DDSTypes;
import extractfields.AnalyzeObject;

public class DecoderManager {

	private static Vector<String> fieldToExtract = new Vector<String>();
	private static Vector< Map<String, String> > vectorOfMapFieldNameValue = new Vector< Map<String, String> >();
	
	private static boolean Endian = Configuration.DECODE_ENDIANISM;
	

	public static void unmarshal(String fileName) throws Exception 
	{
		
		char[] sut 	= new char[Constant.DATE_LENGHT];
		char[] ot 	= new char[Constant.DATE_LENGHT];

		File f = new File(fileName);
		
		String fileDDSConfig = Configuration.DDSCONFIG;
		Map<String, String> DDSConfig = ParserXML.extract(fileDDSConfig);
		
		System.out.println("unmarshalUpdate File name = " + f.getName() + "  " + f.getPath());
		DDSTypeManager.init();
		DDSTypes dds = DDSTypeManager.getDDSTypes(f);

		System.out.println("DDSTypes TopicName = " + dds.getTopicName());
		System.out.println("DDSTypes FileName  = " + dds.getFileName());
		System.out.println("DDSTypes TypeName  = " + dds.getTypeName());
		
		try {
			Class<?> _class = Class.forName( dds.getTypeName() );

			int sizeDDSTopic = Integer.parseInt(DDSConfig.get(dds.getTopicName())) + Constant.HEADER_SIZE_UPDATES;
			System.out.println("sizeDDSTopic  config file : " + Integer.parseInt(DDSConfig.get(dds.getTopicName())) + "  with header --> " + sizeDDSTopic);

			FileInputStream fInStreamOrigin = new FileInputStream(fileName);
			int totalSize = fInStreamOrigin.available();

			// The header is copied at each record. So the total size must be a multiple of the size of one record.
			if ((totalSize > 0) && (totalSize % sizeDDSTopic != 0)) {
				throw new Exception("ERROR : The size of the .rec file is not a multiple of the size of one record.");
			}
			else {

				int recordsNumber = totalSize / sizeDDSTopic;
				System.out.println("recordsNumber : " + recordsNumber);

	       		String[] orbArgs= new String[2];

	       		orbArgs[0] = "-ORBInitRef";
	       		orbArgs[1] = "NameService=corbaname::unused:0";

	       		org.jacorb.orb.ORB orb = (org.jacorb.orb.ORB) org.jacorb.orb.ORB.init(orbArgs, null);
				
				Class<?> HelperClass = Class.forName( dds.getTypeName() + "Helper");
				System.out.println("HelperClass.getName() = " + HelperClass.getName());

				for (int i = 0; i < recordsNumber; i++) {

	   		    	Object object = null;
					byte[] buffer = new byte[sizeDDSTopic];
					
					fInStreamOrigin.read( buffer, 0, sizeDDSTopic);
					
					CDRInputStream io = new CDRInputStream( orb, buffer, Endian); 

	   		    	io.read_char_array(sut, 0,Constant.DATE_LENGHT);
					// System.out.println("SUT=" + new String(sut));
					
					// Retrieve the OT time
					io.read_char_array(ot, 0,Constant.DATE_LENGHT);
					// System.out.println("OT=" + new String(ot));
				
					io.setLittleEndian(Endian);

					long event = io.read_longlong();
					// System.out.println("_event = " + event);
					
					long handle = io.read_longlong();
					// System.out.println("_handle = " + handle);
					
					// An endianess byte occurs just after the handle. He must be skipped, otherwise the alignment would be wrong.
					io.skip(1);

					io.skip(Constant.calculateSkip(dds.getTypeName()));


					if (event != Constant.DELETE_EVENT) {
			        	// Retrieve the  read method (in Helper)
			        	Method ReadMethod = HelperClass.getMethod("read", org.omg.CORBA.portable.InputStream.class);

			        	// Invoke the  Helper to write the data into a file
						object = ReadMethod.invoke(null, io);
						
						
					} else {
						// Create an empty class for deleted events
						object = _class.getConstructors()[0].newInstance();
						
					}

					Map<String, String> mapFieldValue = AnalyzeObject.getInstance().analyzeObject(fieldToExtract, object);
    				
    				vectorOfMapFieldNameValue.add( mapFieldValue);

		        	io.close();
	   			}
	   		}
	   		
			fInStreamOrigin.close();
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
   			
	}	

	
	public static void printObj( Object obj) {
    	System.out.println("obj = " + obj.getClass().getName());
    	
    	if (obj.getClass().getName().equals("com.coflight.cfl.IOData.Common.BasicATM.Misc.WarningOccurenceData")) {

    		WarningOccurenceData wo = (WarningOccurenceData)obj;
	    	
    		System.out.println("warningId --> " +  wo.warningId);
	    	System.out.println("dynamicText --> " +  wo.dynamicText);
	    	System.out.println("timeStamp --> " +  wo.timeStamp);
	    	System.out.println("concernedOEList.size --> " +  wo.concernedOEList.size);
	    	
	    	for (int i = 0; i < wo.concernedOEList.size; i++) {
	    		System.out.println("concernedOEList.OE --> " + wo.concernedOEList.values[i].OE);
			}
    	
    	} else if (obj.getClass().getName().equals("com.coflight.cfl.IOData.External.TechSup.SupervisedObject")) {
    		
    		com.coflight.cfl.IOData.External.TechSup.SupervisedObject wo = (com.coflight.cfl.IOData.External.TechSup.SupervisedObject)obj;
	    	
    		System.out.println("id    --> " +  wo.id);
	    	System.out.println("type  --> " +  wo.type);
	    	System.out.println("value --> " +  wo.value);

    	} else if (obj.getClass().getName().equals("com.coflight.cfl.IOData.External.Flight.ExternalFlight")) {
    		
    		com.coflight.cfl.IOData.External.Flight.ExternalFlight ef = (com.coflight.cfl.IOData.External.Flight.ExternalFlight)obj;
	    	
    		System.out.println("ARCID               --> " +  ef.ARCID);
	    	System.out.println("creationTime        --> " +  ef.creationTime);
	    	System.out.println("extSegmentInfo.size --> " +  ef.extSegmentInfo.size);

    	} else if (obj.getClass().getName().equals("com.coflight.cfl.IOData.External.CorrelationData.CorrelationTopic")) {
    		
    		com.coflight.cfl.IOData.External.CorrelationData.CorrelationTopic ef = (com.coflight.cfl.IOData.External.CorrelationData.CorrelationTopic)obj;

    		System.out.println("ef.isManuallyCorrelated       = " +ef.isManuallyCorrelated);
	    	System.out.println("ef.sicID                      = " +ef.sicID);
	    	System.out.println("ef.sacID                      = " +ef.sacID);
	    	System.out.println("ef.theServiceIdentification   = " +ef.theServiceIdentification);
	    	System.out.println("ef.flightId                   = " +ef.flightId);
	    	System.out.println("ef.techStamp                  = " +ef.techStamp);
	    	System.out.println("ef.CS                         = " +ef.CS);
	    	System.out.println("ef.correlationAmbiguityStatus = " +ef.correlationAmbiguityStatus);
    	}
	}
	
	
	private static void decodeDir( final String dirToUnmarshal, final String typeTopic) {
	    
	    File folder = new File(dirToUnmarshal); 

	     for (final File fileEntry : folder.listFiles()) {

	    	 vectorOfMapFieldNameValue.clear();
             
	    	 System.out.println(fileEntry.getName());
             
             if ( fileEntry.getName().contains(typeTopic) ) {
          	    try {
        			
          	    	// Decode the REC files
        			unmarshal( fileEntry.getAbsolutePath());
        			
        		} catch (Exception e) {
        			// TODO Auto-generated catch block
        			e.printStackTrace();
        		}
            	 
             }
             
    	     Vector <String > vectorInsert = new Vector <String >();  
    		 for (Map<String, String> map : vectorOfMapFieldNameValue) {
    			 
    			 String insertSQL = DBConnection.getInstance().getCreateInsertString(map);
    			 vectorInsert.add(insertSQL);
    		 }
    		 
    		 DBConnection.getInstance().buildInsert(vectorInsert);

	     } // for
	     

	    
	}

	public static void init() {
		
		fieldToExtract.add("ARCID");
		fieldToExtract.add("cancelIndicator");
		fieldToExtract.add("intSegmentInfo.size");
		fieldToExtract.add("intSegmentInfo.values[0].state");
		fieldToExtract.add("intSegmentInfo.values[0].state.value");
		fieldToExtract.add("localID");
		fieldToExtract.add("servedOE.values[0].servedOEname");
		fieldToExtract.add("IFPLId.value");
		fieldToExtract.add("techStamp.itemVersion");
		fieldToExtract.add("techStamp.collectionVersion");
		fieldToExtract.add("routeDetails.departureData.genericDepartureData.value.ADEP.value.code");
		fieldToExtract.add("routeDetails.departureData.genericDepartureData.value.ADEP.value.name.value");
		fieldToExtract.add("aircraftCharacteristics.aircraftType.value");

	}
	

	
	public static void exceuteSelect() {
		
		String query = DBConnection.getInstance().getSampleSelect(fieldToExtract);
		String whereCondition = " WHERE \"ARCID\" LIKE 'AZ%'";
		
		query = query + whereCondition;
		
		ResultSet rs = DBConnection.getInstance().executeQuery(query);
		
	}
	
	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws InterruptedException {
		
		
		 String fileName = "/tmp/" + "DecoderManager.log";
//	     String[] strings = new String[] {
//	                cdmw.common.Options.LOG_LEVEL_OPTION + "=ALL",
//	                cdmw.common.Options.LOG_FILE_OPTION + "=" + fileName};
//
//	    LogManager.Init(strings);

	    init();
	    
	    long startMillis = System.currentTimeMillis();
	    
	    String createTable = DBConnection.getInstance().getCreateTableString(fieldToExtract);
	    System.out.println("createTable = " + createTable);
	    DBConnection.getInstance().buildTable(createTable);
	    
	    String dirToUnmarshal = "/shared/TEMP/pasquale/DAFSRVDecoder/REC/disk1/REC_directories/Session_0001/Updates/Updates-2012.11.05-11.55.25";
	    decodeDir( dirToUnmarshal, "ExternalFlight");
	    
// To check 400 GB : Begin
//      String dirToUnmarshal = "/shared/TEMP/pasquale/TEST_PERFO";
//	    for(int i = 0; i < 40; i++) {
//		    decodeDir( dirToUnmarshal, "ExternalFlight");	    	
//	    }
// To check 400 GB : End
	    
	    long endMillisDecode = System.currentTimeMillis();

	    
	    exceuteSelect();
	    
	    DBConnection.getInstance().close();
	    long endMillisQuery = System.currentTimeMillis();
	    
	    long durationMillisDecode = (endMillisDecode - startMillis);
	    System.out.println("Tot. Millis Decode = " + durationMillisDecode);

	    long durationMillisSelect = (endMillisQuery - endMillisDecode);
	    System.out.println("Tot. Millis Select = " + durationMillisSelect);

	}


}
